home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 12 / Cream of the Crop 12 (Part II) / Cream of the Crop 12 (Part II).iso / OS2 / OS2CL016.ZIP / PMPP.DOC < prev    next >
Encoding:
Text File  |  1996-05-05  |  14.9 KB  |  388 lines

  1.  
  2.  
  3.  
  4.  
  5.     PM++
  6.     
  7.     Version 0.08
  8.     11-26-1994
  9.  
  10.     Version 0.15
  11.     10-03-1995
  12.  
  13.     Version 0.16
  14.     04-25-1996
  15.     
  16.     Giovanni Iachello
  17.  
  18.     A freeware class library for the Presentation Manager API
  19.     
  20.  
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.     1. Introduction
  35.     
  36.     This manual page is written in my terrible english, but  considering
  37. that "Real Programmers Don't Read Manuals", I feel it's enough.  PM++ is
  38. a freeware class library that encapsulates some of the OS/2 Presentation
  39. Manager API calls.  I developed it using the emx distribution of the GNU
  40. C++  Compiler with the general idea of writing some support programs for
  41. programmers who want to  write presentation manager applications without
  42. buying  expensive  compilers.   It  is  obvious  that  for  professional
  43. applications some tools distributed with  the  commercial  packages  are
  44. needed  (particulary  the  help  compiler,  CASE tools etc etc), but for
  45. normal, small, programs emx should be sufficient.
  46.  
  47.     With this idea the first  step  was  finding  out what is missing to
  48. emx's PM support.  This led me to a class library to encapsulate the  PM
  49. API.
  50.  
  51.     My  library  is  similar,  in the general design, to Paul DiLascia's
  52. Windows++ library: it's simple, small,  and  adds only a very thin layer
  53. between OS/2 and C++ programs to PM  applications,  to  the  benefit  of
  54. effincency and size.  It is compiled in a 32-bit DLL, to save disk space
  55. on multiple, or different, programs that use it.
  56.  
  57.  
  58.  
  59.     2. Support Classes
  60.     
  61.     There  is a certain number of support classes, which make it easy to
  62. deal with some of  the  most  used  PM  data  types and structures.  For
  63. example there is a PMPoint class which derives from the POINTL structure
  64. and overloads the +, -, * operators, with their obvious  functions.   It
  65. is  possible  to  pass  a  PMPoint structure to an PM API function which
  66. expects a PPOINTL pointer, and  there  are inline functions to query the
  67. single members of the internal POINTL structures (x and  y).   There  is
  68. also  a  PMRect class which is very similar to the PMPoint class, except
  69. for the fact that the PM structure it encapsulates is a RECTL.
  70.  
  71.     Then there are the  PMAnchorBlock, PMMessageQueue and PMApp classes;
  72. the first two classes contatin respectivly a HAB and a HMQ, and add some
  73. special constructors and 'dumb' inline functions  that  mirror  PM  APIs
  74. which  refer to the HAB or HMQ.  (For example WinGetMsg, etc.) The PMApp
  75. class is the main class for  a PM++ application and contains the command
  76. line parameters,  a  PMAnchorBlock  and  a  PMMessageQueue,  and  a  few
  77. functions  to  process  the  window  messages  of the application's main
  78. thread.  With these classes  the  main()  function of a PM++ application
  79. can be as simple as:
  80.  
  81.     PMApp *App;
  82.  
  83.     int main (int argc,char* argv[])
  84.     {
  85.         PMAnchorBlock ab;
  86.         PMMessageQueue mq;
  87.         ab.init();
  88.         mq.create(ab);
  89.         
  90.         App=new PMApp(ab,mq,argc,argv);
  91.     
  92.         PMWin * w=new PMWin(ab);
  93.         w->createWin();
  94.         
  95.         App->run();
  96.     
  97.         w->destroyWin();
  98.     
  99.         mq.destroy();
  100.         ab.uninit();
  101.     
  102.         return (0);
  103.     }
  104.  
  105.     The PMIniProfile class eases the access to the Profile files (Prf...
  106. APIs).
  107.  
  108.     The PMThread class automatically  creates  a  new thread in the PM++
  109. application.  Using a clever :) hack the thread procedure is  a  virtual
  110. member  of  PMThread; this makes it possible to add thread instance data
  111. by simply deriving a subclass from PMThread and adding data fields.  The
  112. main procedure of the  derived  class  can  access to those data members
  113. just as if it were a normal member of the derived class.  I  added  also
  114. support  for the non-standard thread instance data functions supplied by
  115. the emx library,  and  a  series  of  functions  to  change the thread's
  116. settings.
  117.  
  118.     The PMWindowThread is  very  similar  to  a  normal thread; the only
  119. difference is that it builds automatically a PMAnchorBlock,  simplifying
  120. the implementation of threads using some of the PM APIs.  It is possible
  121. to  use  PMWindowThread  to  write  printer threads, like in the example
  122. program, or slow window drawing threads.
  123.  
  124.     The PMEvent structure encapsulates  the message data normally passed
  125. to the window message procedure, plus a PCHRMSG and a  PMSEMSG  to  ease
  126. access  to  the  CHRMSG  and  MSEMSG  structures passed with WM_CHAR and
  127. WM_mouse messages.  The ret field is used to return a MRESULT value from
  128. message handling functions.
  129.  
  130.  
  131.  
  132.     3. Window Class Hierarchy
  133.     
  134.     The base class is obviously PMWin: this class contains some data  (a
  135. PMAnchorBlock, the window handle, the frame window handle, and a pointer
  136. to  a  CreateArgs  structure, which is used during the window creation).
  137. The PM window is  not  created  in  the constructor: only the CreateArgs
  138. structure is filled.  The PM  window  is  than  created  by  a  separate
  139. functions.   With this hack it is possible for derived classes to change
  140. some CreateArgs in the constructor  before  the window is created.  Once
  141. allocated with the new operator,  a  PMWin  is  never  deleted:  when  a
  142. WM_DESTROY  message  arrives  to the window message procedure, the PMWin
  143. object is automatically deleted by the  PM++ system.  There are a lot of
  144. inline functions to hide the PM APIs that refer  to  the  window  handle
  145. (HWND),  and  some  inline  functions  to query the internal data of the
  146. PMWin class (the HWND etc.)  There  is  also a certain number of virtual
  147. functions for processing the most common messages (WM_PAINT, WM_COMMAND,
  148. WM_CHAR...).  All other messages are processed in the other() function.
  149.  
  150.     The PMWin object (and all derived classes) is connected to the  HWND
  151. troughall  the  whole  system  with  the  typical  WinSet/QueryWindowPtr
  152. method,  with  the PMWin pointer stored in the QWP_USER position (offset
  153. 0).  This lets the standard  C  window procedure call always the message
  154. dispacher routine of the right PMWin  object,  without  allocating  more
  155. window instance data.
  156.  
  157.     PMWin  is  the  base  class  for PMMainWin, which adds some standard
  158. functions for main  application  window  (special  menu selections: file
  159. open, file new, etc., and a special version of the paint function  which
  160. gets  a  ready-to-use  referece to a PMPresSpace (the PM++ equivalent of
  161. the HPS).
  162.  
  163.     The message processing virtual  functions  must return FALSE if they
  164. don't process the message (so that the message dispatcher will call  the
  165. default PM routine), or TRUE if they do.  The return code of the message
  166. processing  (MRESULT  in  PM  jargon)  can  be set by the message return
  167. function trough the ret field of the PMEvent structure.
  168.  
  169.     The PMSubclassWin class is  a  special  window class that permits to
  170. create   PMWindow   objects   for    subclassed    windows    via    the
  171. WinSubclassWindow.   The  only  difference  from the normal PMWin is the
  172. constructor and the createWin function, while all the other parts of the
  173. PMWin class work just as usual.
  174.  
  175.     The PMMenu class load and popups menus; an example of how to uses it
  176. can be found in the Dialog Editor program.
  177.  
  178.  
  179.     4. The Graphics Interface
  180.     
  181.     The PMPointer class  is  used  to  access  automatically the pointer
  182. handling functions of the PM API: WinLoadPointer and WinSetPointer.   It
  183. is  possible to load a pointer with the constructor and to set it as the
  184. system pointer using the  set  routine.   The reset routine restores the
  185. arrow as the default pointer.
  186.  
  187.     The PMDeviceContext class permits to open, handle, and close  Device
  188. Contexts.   This  is  the  base class for the PMPrinterDC and PMMemoryDC
  189. classes which automatically create a  DC  for  the default printer and a
  190. memory device context compatible to the supplied  DC.   The  PMPrinterDC
  191. offers  also  functions to call the system setup dialog for the printer,
  192. to start a document and to end it.
  193.  
  194.     The PMPresSpace class encapsulates some of the Gpi...  functions and
  195. comes in various flavors: PMWindowPresSpace (a PS obtained from a Window
  196. handle,  used   by   the   paint   message   processing   routine),  and
  197. PMMicroCachedPresSpace (a m.c.  PS also obtained from a Window handle.),
  198. and PMPresSpace, connected to a supplied PMDeviceContext.
  199.  
  200.     Printing is very easy with these supplied classes: a sample printout
  201. can be produced with as little code as:
  202.  
  203.     PMPrinterDC printer(hab); // create an instance of a PMPrinterDC
  204.     printer.open();             // open the DC
  205.     printer.startDoc("Test Document");
  206.  
  207.     PMPresSpace *ptr=new
  208.     PMPresSpace(&printer, 1000, 1000,
  209.         PU_ARBITRARY|PU_LOENGLISH|GPIF_DEFAULT|GPIT_NORMAL|GPIA_ASSOC, hab);
  210.  
  211.     //    [draw on ptr]
  212.  
  213.     delete ptr;
  214.     printer.endDoc("Test Document");
  215.  
  216.     
  217.  
  218.     5. The Dialog Subsystem
  219.     
  220.     The dialog handling is quite sophisticated, but very simple to  use:
  221. for  most dialog windows it is not necessary to write a message handling
  222. function because dialogs derived  from PMModalDialog or PMModelessDialog
  223. receive automatically from them most of the normal  processing  involved
  224. in  dialog  functions.   It  is  only  necessary  to build a table which
  225. connects each dialog control to  a  C++ data structure; the following is
  226. an example of a simple dialog box with two entry fields connected to two
  227. char arrays in a C++ structure (dlgsize):
  228.  
  229.     struct _dlgsize { // define and create dlgsize
  230.         char sx[10];
  231.         char sy[10];
  232.     } dlgsize;
  233.     // create table which connects each control (the DSIZE... macros
  234.     // are defined in an include file common to the .cpp and .rc sources)
  235.     // to the members of the _dlgsize structure
  236.     static PMControlMap ctrlmap[]={ 
  237.         cmEntryField(DSIZE_EF_SX,_dlgsize,sx)
  238.         cmEntryField(DSIZE_EF_SY,_dlgsize,sy)
  239.         cmEnd(DSIZE_EF_SX)   // set default active control
  240.     };
  241.     // initalize the dlgsize structure
  242.     sprintf(dlgsize.sx,"%d",100);
  243.     sprintf(dlgsize.sy,"%d",100);
  244.     // create a dialog box, using the dlgsize structure as data area for
  245.     // storing the user's inputs.
  246.     PMModalDialog sizedlg(HWND_DESKTOP,hwnd,DLG_SIZE,ctrlmap,&dlgsize);
  247.     int ret=sizedlg.createWin();
  248.     if (ret) {
  249.         // use data in dlgsize...
  250.     }
  251.  
  252.     If very 'interactive' dialogs are needed you can just derive a class
  253. from one of the PMDialog...  classes and add the needed functionalities.
  254. The PMDialog class (base  for  PMModelessDialog  and  PMModalDialog)  is
  255. derived  from the PMWin class and adds only a functions and data members
  256. typical of dialog windows; it inherits form PMWin all standard functions
  257. (inline and virtual).
  258.  
  259.     The  File  and  Font   system   default   dialog  windows  are  also
  260. encapsulated, and it is possible to change their behaviour just  as  for
  261. normal dialogs.
  262.  
  263.     The  dialog  window keeps a list of PMControl objects which refer to
  264. the dialog controls.  PMControl is  inherited  from PMWin, so all inline
  265. functions are inherited form PMWin.   PMControl  has  also  two  virtual
  266. functions (get and set) which permit to get and set the control specific
  267. data in an uniform and control-independent way.
  268.     The first implementation of the PMControl class used to set the USER
  269. window pointer to  the  address  of  the PMControl object; unfortunately
  270. some of the control don't allow to set the USER window pointer,  and  so
  271. the  controlFromID  function  must use a different technique to retrieve
  272. the pointer to the PMControl  object  (the  pointer is also mantained in
  273. the control list structure, and a linear search is performed  each  time
  274. the pointer to the control is requested.)
  275.  
  276.  
  277.     6. The IPF Help Subsystem
  278.     
  279.     Support for managing the help subsystem is provided.  There are five
  280. procedures trough which help panels    can be showed:
  281.  
  282. 1. Help on menuitems: the user presses F1 while on a menu selection.
  283. 2. Dialog controls: the user presses F1 or the Help button while in
  284.    a dialog box, and the help must be context-sensitive to the single
  285.    control, or, otherwise, must be at least specific to the dialog
  286.    window.
  287.  
  288. 1. and 2. are automatically handled by the system (remember that the
  289.    dialogs must be owned by the client window, NOT by the frame window
  290.    of the application).
  291.  
  292. 3. Help from the Help pull-down menus (Index, General, Using, Keys)
  293.    automagically handled by the system, except for the Keys help
  294.    panel query (HM_QUERY_KEYS_HELP) which must be answered by the 
  295.    application (the active keys may change during the execution of 
  296.    the program).
  297.  
  298. 4. Common Dialog Boxes: the font and file dialogs send a WM_HELP message
  299.    to the owner, which activates the extended help panel for the dialog.
  300.    Control-specific panels for the common dialog boxes are not yet 
  301.    supported.
  302.    
  303. 5. Help from Message Boxes, handled trough the help Hook function
  304.    (must be defined and set by the application).
  305.  
  306.     Notes:
  307.     
  308.     All  the HM_* messages are handled via the helpmsg virtual function,
  309. while the WM_HELP message is handled via the help function.
  310.  
  311.     The hook  function  must  process  only  help  requests  done in the
  312. message boxes.  This means that it must check the usTopic  parameter  to
  313. see  if  it  comes from a message box.  If it does, a message is sent to
  314. the Help Instance to show the help panel of the message box.  If it does
  315. not, the hook function  must  *not*  process  the  help request (see the
  316. example program).
  317.  
  318.  
  319.     7. Threads
  320.     
  321.     It is very easy to use secondary threads with PM++: see provadlg.cpp
  322. for an example of separate print  thread.   The case of a separate paint
  323. thread for the client window is more interesting:  see  bg_paint.cpp for 
  324. an example of this. 
  325.  
  326.     8. Know Bugs
  327.     
  328.     None. (!)
  329.  
  330.  
  331.     9. Important notice
  332.  
  333.     This library is provided AS IS with no warranty that  it  will  meet
  334. your needs or perform as expected and with no support from my side.
  335.  
  336.                    This is freeware software.  
  337.     
  338.     You  can  modify  or  use  this  code  as you wish, provided that my
  339. portion of the  code  reamins  freeware  (i.e.   available to anyone, in
  340. source code form) and that you keep my notice at the beginning  of  each
  341. file.
  342.  
  343.     If  you  discover  bugs  or if you want to help me in developing new
  344. versions of the library, you can contact me at:
  345.  
  346.     Giovanni Iachello
  347.     giac@dei.unipd.it
  348.  
  349.     on the Internet or at:
  350.  
  351.     Giovanni Iachello
  352.     2:333/300.22 
  353.  
  354.     on Fidonet.
  355.  
  356.  
  357.     10. Bibliography
  358.     
  359.     "OS/2 Presentation Manager Programming", Charles Petzold, Ziff-Davis
  360. Press, 1994. ISBN 1-56276-123-4
  361.  
  362.     "The Art of OS/2 2.1 C Programming", Panov, Salomon and Panov,
  363. Wiley-Qed, 1993. ISBN 0-471-58802-4
  364.  
  365.     "Windows++", Paul DiLascia, Addison Wesley, 1992. ISBN 0-201-60891-X
  366.     
  367.     "The Hitchhikers Guide To the Galaxy", Douglas Adams
  368.     
  369.     And also other  very  interesting  magazines and pubblications, like
  370. the EDMI/2 free electronic OS/2 programmer's magazine  (kudos  to  Larry
  371. Salomon Jr.!), and many programming examples on the various OS/2 support
  372. sites on the internet.  A special "thanks!" must go to  Eberhard Mattes,
  373. for his excellent work on the EmTex and EMX packages.
  374.     
  375.     
  376.  
  377.     11. Biographical notes
  378.     
  379.     The  author  of this class library is me, Giovanni Iachello.  I'm 21
  380. years old and  I'm  a  3rd  year  Software  Engineering student at Padua
  381. University  in  Padua,  Italy.   My  hobbies  include  skiing,   playing
  382. role-play   games,  listening  to  *good*  music,  programming  (!)  and
  383. discovering this strange world.
  384.  
  385.  
  386.  
  387.  
  388.